#include "Parse.h"
#include <stdlib.h>


#ifdef __DEBUG__
extern FILE* p_trace_file;
#endif

// the keywords of command
char* p_select		= "select";
char* p_from		= "from";
char* p_where		= "where";
char* p_update		= "update";
char* p_set		= "set";
char* p_insert		= "insert";
char* p_delete		= "delete";
char* p_connect	= "connect";
char* p_run			= "run";
char* p_and		= "and";
char* p_or		= "or";
char* p_values		= "values";
char* p_into		= "into";
char* p_to		= "to";
char* p_server		= "server";
char* p_user		= "user";
char* p_password	= "password";
char* p_create		= "create";
char* p_database	= "database";
char* pc_table		= "table";
char* p_not		= "not";
char* p_null		= "null";
char* p_default		= "default";
char* p_primary	= "primary";
char* p_key		= "key";
char* p_max_size	= "max_size";
char* p_on		= "on";
char* p_log		= "log";
char* p_varchar	= "varchar";
char* p_int		= "int";
char* p_float		= "float";


// the notaions used in the command
char c_semicolon		= ';';
char c_tab				= '\t';
char c_ws				= ' ';
char c_comma			= ',';
char c_equal			= '=';
char c_quote			= '\'';
char c_greater			= '>';
char c_smaller			= '<';
char c_dot				= '.';
char c_asterisk			= '*';
char c_lbracket			= '(';
char c_rbracket			= ')';
char c_colon			= ':';
char c_line_feed			= 10;
char c_new_line			= '\n';




BOOL_EX char_is_in(char* p_string, char c_target)
{
	int i_length;
	int i = 0;

	i_length = strlen(p_string);
	for(i = 0;i  < i_length; ++ i)
	{
		if(p_string[i] == c_target)
		{
			return TRUE;
		}
	}
	return FALSE;
}

void lower_ex(char* p_char, int i_len)
{
	int i = 0;
	for(i = 0; i < i_len; ++ i)
	{
		if(p_char[i] <= 'Z' && p_char[i] >= 'A')
		{
			p_char[i] = p_char[i] + 32;
		}
	}
}

// Return : FALSE if the index has reached the end, TRUE otherwise
BOOL_EX skip_ws(char* p_cmd, int* p_index, int i_length)
{
	while ( (*p_index) < i_length && is_end_char(p_cmd, *p_index) == TRUE)
	{
		++ (*p_index);
	}
	if((*p_index) == i_length)
	{
		// The index has reached the end 
		return FALSE;
	}
	// The index has not reached the end
	return TRUE;
}

BOOL_EX is_end_char(char* p_cmd, int i_index)
{
	if(p_cmd[i_index] == c_comma || p_cmd[i_index] == c_ws 
		||p_cmd[i_index] == c_tab || p_cmd[i_index] == c_semicolon 
		|| p_cmd[i_index] == c_lbracket || p_cmd[i_index] == c_rbracket
		||  p_cmd[i_index] == c_line_feed || p_cmd[i_index] == c_new_line
		)
	{
		return TRUE;
	}
	return FALSE;
}
BOOL_EX is_operator(char c_char)
{
	if(c_char == c_equal || c_char == c_greater || c_char == c_smaller)
		return TRUE;
	return FALSE;
}

BOOL_EX is_number(char c_char)
{
	if(c_char >= '0' && c_char <= '9')
		return TRUE;
	return FALSE;
}
/*
param0: the original string
param1: current index of the string
param2: the new char to be appended
param3: the increased size of the string
param4: current size of the string
*/
void append_char(char** pp_string, int* p_cur_index, char c_new_char, int i_value_power, int* p_cur_size)
{
	if((*p_cur_index) == (*p_cur_size))
	{
		(*p_cur_size) += i_value_power;
		if((*p_cur_index) == 0)
		{
			(*pp_string) = (char*)malloc(sizeof(char) * (*p_cur_size));
		}
		else 
		{
			(*pp_string) = (char*)realloc((*pp_string), sizeof(char) * (*p_cur_size));  
		}
	}
	(*pp_string)[(*p_cur_index) ++] = c_new_char;
}

// param0: the string array's address
// param1: current index of the array
// param2: the new string
// param3: the new string's length
// param4: the increase step of the array
// param5: the current size of the array
void append_string(char*** ppp_string, int* p_cur_index, char* p_new_string, int i_new_str_len, int i_value_power, int* p_cur_size)
{
	if((*p_cur_index) == (*p_cur_size))
	{
		(*p_cur_size) += i_value_power;
		if((*p_cur_index) == 0)
		{
			(*ppp_string) = (char**)malloc(sizeof(char*) * (*p_cur_size));
		}
		else 
		{
			(*ppp_string) = (char**)realloc((*ppp_string), sizeof(char*) * (*p_cur_size));  
		}
	}
	(*ppp_string)[(*p_cur_index)] = (char*) malloc(sizeof(char) * i_new_str_len);
	strcpy((*ppp_string)[(*p_cur_index) ++], p_new_string);
}

void append_expr(expr_t **pp_expr, int* p_cur_index,expr_t new_expr , int i_value_power, int* p_cur_size)
{
	if((*p_cur_index) == (*p_cur_size))
	{
		(*p_cur_size) += i_value_power;
		if((*p_cur_index) == 0)
		{
			(*pp_expr) = (expr_t*)malloc(sizeof(expr_t) * (*p_cur_size));
		}
		else 
		{
			(*pp_expr) = (expr_t*)realloc((*pp_expr), sizeof(expr_t) * (*p_cur_size));  
		}
	}
	(*pp_expr)[(*p_cur_index) ++] = new_expr;
}

void append_pair(pair_t **pp_pair, int* p_cur_index, pair_t new_pair, int i_value_power, int* p_cur_size)
{
	if((*p_cur_index) == (*p_cur_size))
	{
		(*p_cur_size) += i_value_power;
		if((*p_cur_index) == 0)
		{
			(*pp_pair) = (pair_t*)malloc(sizeof(pair_t) * (*p_cur_size));
		}
		else 
		{
			(*pp_pair) = (pair_t*)realloc((*pp_pair), sizeof(pair_t) * (*p_cur_size));  
		}
	}
	(*pp_pair)[(*p_cur_index) ++] = new_pair;
}


// 3: _out, The fourth parameter is the result string char[257]
// 4: _out, The last parameter is 1 larger than the length of the string
grammar_chck_value get_a_word(char* p_cmd, int* p_index, int i_length, char* p_word, int* p_word_len, int i_max_length)
{

	// SKIP all the wide space or tab character
	// If has reached the end
	if(skip_ws(p_cmd, p_index, i_length) == FALSE)
	{
		return GRAMMAR_REACH_END;
	}
	(*p_word_len) = 0;
	while( (*p_index) < i_length && is_end_char(p_cmd, *p_index)  == FALSE )
	{
		p_word[(*p_word_len) ++] = p_cmd[(*p_index)];
		if((*p_word_len) == i_max_length)
		{
			if(is_end_char(p_cmd, (*p_index) + 1) == FALSE)
			{
				return GRAMMAR_NAME_TOO_LONG;
			}
		}
		++ (*p_index);
	}
	p_word[(*p_word_len) ++] = '\0';
	return GRAMMAR_SUCCESS;
}

grammar_chck_value get_a_word_until_comma(char* p_cmd, int* p_index, int i_length, char* p_word, int* p_word_len, int i_max_length)
{

	while ((*p_index) < (i_length - 1) && is_end_char(p_cmd, *p_index) == TRUE && p_cmd[*p_index] != c_comma)
	{
		++ (*p_index);
	}
	if((*p_index) == (i_length - 1)|| p_cmd[*p_index] == c_comma)
	{
		return GRAMMAR_REACH_END;
	}
	// SKIP all the wide space or tab character
	// If has reached the end
	(*p_word_len) = 0;
	while( (*p_index) < i_length && is_end_char(p_cmd, *p_index)  == FALSE )
	{
		p_word[(*p_word_len) ++] = p_cmd[(*p_index)];
		if((*p_word_len) == i_max_length)
		{
			if(is_end_char(p_cmd, (*p_index) + 1) == FALSE)
			{
				return GRAMMAR_NAME_TOO_LONG;
			}
		}
		++ (*p_index);
	}
	//if((*p_index) == i_length)
	//{
	//	return GRAMMAR_REACH_END;
	//}
	p_word[(*p_word_len) ++] = '\0';
	return GRAMMAR_SUCCESS;
}

grammar_chck_value get_inner_quote_info(char* p_cmd, int* p_index, int i_length, char* p_word, int* p_word_len, int i_max_length)
{

	// SKIP all the wide space or tab character
	// If has reached the end
	if(skip_ws(p_cmd, p_index, i_length) == FALSE)
	{
		return GRAMMAR_REACH_END;
	}
	if(p_cmd[(*p_index)] == c_quote)
	{
		++ (*p_index);
	}
	(*p_word_len) = 0;
	while( (*p_index) < i_length && p_cmd[(*p_index)]  != c_quote)
	{
		p_word[(*p_word_len) ++] = p_cmd[(*p_index)];
		if((*p_word_len) == i_max_length)
		{
			if( p_cmd[(*p_index) + 1]  != c_quote)
			{
				return GRAMMAR_NAME_TOO_LONG;
			}
		}
		++ (*p_index);
	}
	++ (*p_index);
	p_word[(*p_word_len) ++] = '\0';
	return GRAMMAR_SUCCESS;
}

grammar_chck_value get_bracket_values(char* p_cmd_str, int *p_index, int i_length, char*** ppp_new_values, int *p_value_count, BOOL_EX check_string)
{
	char p_temp[INFINITY_P1];
	int i_temp_len = 0;
	grammar_chck_value ret;
	int i_increase_power = 3;
	int i_cur_size = 0;
	int i = 0;
	int i_dot_count = 0;

	if(skip_ws(p_cmd_str, p_index, i_length) == FALSE)
	{
		return GRAMMAR_REACH_END;
	}
	-- (*p_index);
	// skip the '('
	if(p_cmd_str[(*p_index)] != c_lbracket)
	{
		return GRAMMAR_NO_LBRACKET;
	}
	++ (*p_index); 

	/* ===============get the  values===============*/
	while ((ret = get_a_word(p_cmd_str,p_index, i_length, p_temp, &i_temp_len, INFINITY)) == GRAMMAR_SUCCESS)
	{
		if(check_string)
		{
			if(p_temp[0] == c_quote)
			{
				if(p_temp[i_temp_len - 2] != c_quote)
				{
					return GRAMMAR_UNMATCHED_QUOTE;
				}
				p_temp[i_temp_len - 2] = 0;
				for (i = 0; p_temp[i] != 0; ++ i)
				{
					p_temp[i] = p_temp[i + 1];
				}
			}
			else
			{
				for (i = 0; i < i_temp_len - 1; ++ i)
				{
					if(! is_number(p_temp[i]))
					{
						if(i_dot_count == 0 && p_temp[i] == c_dot)
						{
							i_dot_count = 1;
						}
						else
						{
							return GRMMAR_MISSING_QUOTE;
						}
					}
				}
			}
		}
		else
		{
			if(p_temp[0] == c_quote)
			{
				if(p_temp[i_temp_len - 2] != c_quote)
				{
					return GRAMMAR_UNMATCHED_QUOTE;
				}
				p_temp[i_temp_len - 2] = 0;
				for (i = 0; p_temp[i] != 0; ++ i)
				{
					p_temp[i] = p_temp[i + 1];
				}
			}
		}
		// append the column name to the back of the column_name of the select struct.
		append_string(
			ppp_new_values,
			p_value_count, 
			p_temp, 
			i_temp_len,
			i_increase_power,
			&i_cur_size
			);
		if(p_cmd_str[(*p_index)] == c_rbracket)
		{
			break;
		}
	}
	if(ret == GRAMMAR_NAME_TOO_LONG)
	{
		return ret;
	}
	if(p_cmd_str[(*p_index)] == c_rbracket)
	{
		++ (*p_index);
		return GRAMMAR_SUCCESS;
	}
	else
	{
		return GRAMMAR_NO_RBRACKET;
	}
	/* ===============end===============*/
}


grammar_chck_value parse_select_command(char* p_cmd_str, int i_index, int i_length, cmd_t *p_cmd)
{
	char p_temp[MAX_NAME_LENGTH_P1];
	int i_temp_len = 0;
	grammar_chck_value ret;
	int i_increase_power = 3;
	int i_cur_size = 0;

	p_cmd->type = SELECT;
	p_cmd->cmd_struct.select_struct.i_column_name_count = 0;
	p_cmd->cmd_struct.select_struct.i_condition_count = 0;
	p_cmd->cmd_struct.select_struct.i_table_count = 0;
	p_cmd->cmd_struct.select_struct.pp_column_name = NULL;
	p_cmd->cmd_struct.select_struct.p_expr = NULL;
	p_cmd->cmd_struct.select_struct.pp_table_name = NULL;

	/* ===============get the column names===============*/
	while ((ret = get_a_word(p_cmd_str,&i_index, i_length, p_temp, &i_temp_len, MAX_NAME_LENGTH)) == GRAMMAR_SUCCESS)
	{
		// If reached to the "from" keyword, then break.
		if(strcmp(p_temp, p_from) == 0)
		{
			break;
		}
		// append the column name to the back of the column_name of the select struct.
		else
		{
			append_string(
				&p_cmd->cmd_struct.select_struct.pp_column_name,
				&p_cmd->cmd_struct.select_struct.i_column_name_count, 
				p_temp, 
				i_temp_len,
				i_increase_power,
				&i_cur_size
				);
		}
	}
	if(ret == GRAMMAR_NAME_TOO_LONG)
	{
		return ret;
	}
	if(ret == GRAMMAR_REACH_END)
	{
		return GRAMMAR_EARLY_END;
	}
	if (p_cmd->cmd_struct.select_struct.i_column_name_count == 0)
	{
		return GRAMMAR_NO_COLUMN_NAME_SPECIFIED;
	}
	/* ===============end===============*/

	/* ===============get the table names===============*/
	i_cur_size = 0;
	while ((ret = get_a_word(p_cmd_str,&i_index, i_length, p_temp, &i_temp_len, MAX_NAME_LENGTH)) == GRAMMAR_SUCCESS)
	{
		// If reached to the "where" keyword, then break.
		if(strcmp(p_temp, p_where) == 0)
		{
			break;
		}
		// append the column name to the back of the column_name of the select struct.
		else
		{
			append_string(
				&p_cmd->cmd_struct.select_struct.pp_table_name,
				&p_cmd->cmd_struct.select_struct.i_table_count, 
				p_temp, 
				i_temp_len,
				i_increase_power,
				&i_cur_size
				);
		}
		// to judge that if the parse has reached the end
		if(i_index == i_length)
		{
			if(p_cmd->cmd_struct.select_struct.i_table_count == 0)
			{
				return GRAMMAR_NO_TABLE;
			}
			else
			{
				return GRAMMAR_SUCCESS;
			}
		}
	}
	if(ret == GRAMMAR_NAME_TOO_LONG)
	{
		return ret;
	}
	else if(ret ==  GRAMMAR_REACH_END)
	{
		return GRAMMAR_NO_TABLE;
	}
	/* ===============end===============*/
	skip_ws(p_cmd_str, &i_index, i_length);
	if (i_length == i_index)
	{
		return GRAMMAR_SUCCESS;
	}
	/* ===============get the conditions===============*/
	return split_expression(p_cmd_str,
		&i_index, 
		i_length, 
		p_cmd,
		i_increase_power);
	/* ===============end===============*/

}


grammar_chck_value parse_delete_command(char* p_cmd_str, int i_index, int i_length, cmd_t *p_cmd)
{
	grammar_chck_value ret;
	char p_temp[MAX_NAME_LENGTH_P1];
	int i_temp_len = 0;
	int i_increase_power = 3;
	int i_cur_size = 0;

	p_cmd->type = DELETE;
	p_cmd->cmd_struct.delete_struct.i_condition_count = 0;
	p_cmd->cmd_struct.delete_struct.p_expr = NULL;

	ret = get_a_word(p_cmd_str,&i_index, i_length, p_temp, &i_temp_len, MAX_NAME_LENGTH);
	// to judge that if the parse has reached the end
	if(ret == GRAMMAR_NAME_TOO_LONG)
	{
		return ret;
	}
	if(i_index == i_length || ret == GRAMMAR_REACH_END )
	{
		return GRAMMAR_EARLY_END;
	}

	if(strcmp(p_temp, p_from) != 0)
	{
		return GRAMMAR_NO_FROM;
	}

	/* ===============get the table name===============*/
	ret = get_a_word(p_cmd_str,&i_index, i_length, p_temp, &i_temp_len, MAX_NAME_LENGTH);
	// to judge that if the parse has reached the end
	if(ret == GRAMMAR_NAME_TOO_LONG)
	{
		return ret;
	}
	strcpy(p_cmd->cmd_struct.delete_struct.p_table_name, p_temp);
	if(i_index == i_length || ret == GRAMMAR_REACH_END)
	{
		return GRAMMAR_SUCCESS;
	}
	/* ===============end===============*/

	/* ===============Check The 'where'===============*/
	ret = get_a_word(p_cmd_str,&i_index, i_length, p_temp, &i_temp_len, MAX_NAME_LENGTH);
	// to judge that if the parse has reached the end
	if(ret == GRAMMAR_NAME_TOO_LONG)
	{
		return ret;
	}
	if(i_index == i_length || ret == GRAMMAR_REACH_END)
	{
		return GRAMMAR_EARLY_END;
	}
	if(strcmp(p_temp, p_where) != 0)
	{
		return GRAMMAR_NO_WHERE;
	}
	/* ===============end===============*/

	/* ===============get the conditions===============*/
	return split_expression(p_cmd_str,
		&i_index, 
		i_length, 
		p_cmd,
		i_increase_power);
	/* ===============end===============*/
}


grammar_chck_value parse_update_command(char* p_cmd_str, int i_index, int i_length, cmd_t *p_cmd)
{
	char p_temp[MAX_NAME_LENGTH_P1];
	int i_temp_len = 0;
	grammar_chck_value ret;
	int i_increase_power = 3;
	int i_cur_size = 0;

	p_cmd->type = UPDATE;
	p_cmd->cmd_struct.update_struct.i_condition_count = 0;
	p_cmd->cmd_struct.update_struct.i_new_value_count = 0;
	p_cmd->cmd_struct.update_struct.p_expr = NULL;
	p_cmd->cmd_struct.update_struct.p_pair = NULL;


	/* ===============get the table name===============*/
	ret = get_a_word(p_cmd_str,&i_index, i_length, p_temp, &i_temp_len, MAX_NAME_LENGTH);
	// to judge that if the parse has reached the end
	if(ret == GRAMMAR_NAME_TOO_LONG)
	{
		return ret;
	}

	if(i_index == i_length || ret == GRAMMAR_REACH_END)
	{
		return GRAMMAR_EARLY_END;
	}
	strcpy(p_cmd->cmd_struct.update_struct.p_table_name, p_temp);
	/* ===============end===============*/

	/* ===============Check The 'Set'===============*/
	ret = get_a_word(p_cmd_str,&i_index, i_length, p_temp, &i_temp_len, MAX_NAME_LENGTH);
	// to judge that if the parse has reached the end
	if(ret == GRAMMAR_NAME_TOO_LONG)
	{
		return ret;
	}
	if(i_index == i_length || ret == GRAMMAR_REACH_END)
	{
		return GRAMMAR_EARLY_END;
	}
	if(strcmp(p_temp, p_set) != 0)
	{
		return GRAMMAR_NO_SET;
	}
	/* ===============end===============*/

	/* ===============get the new values===============*/
	ret = split_equation(p_cmd_str, &i_index, i_length, p_cmd, &i_cur_size, i_increase_power);
	if(ret != GRAMMAR_SUCCESS)
	{
		return ret;
	}
	/* ===============end===============*/

	/* ===============Check The 'where'===============*/
	ret = get_a_word(p_cmd_str,&i_index, i_length, p_temp, &i_temp_len, MAX_NAME_LENGTH);
	// to judge that if the parse has reached the end
	if(ret == GRAMMAR_NAME_TOO_LONG)
	{
		return ret;
	}
	if(i_index == i_length || ret == GRAMMAR_REACH_END)
	{
		return GRAMMAR_EARLY_END;
	}
	if(strcmp(p_temp, p_where) != 0)
	{
		return GRAMMAR_NO_WHERE;
	}
	/* ===============end===============*/

	/* ===============get the conditions===============*/
	return split_expression(p_cmd_str,
		&i_index, 
		i_length, 
		p_cmd,
		i_increase_power);
	/* ===============end===============*/

}

grammar_chck_value parse_insert_command(char* p_cmd_str, int i_index, int i_length,cmd_t *p_cmd)
{
	grammar_chck_value ret;
	char p_temp[MAX_NAME_LENGTH_P1];
	int i_temp_len = 0;
	int i_increase_power = 3;
	int i_cur_size = 0;

	p_cmd->type = INSERT;
	p_cmd->cmd_struct.insert_struct.i_column_count = 0;
	p_cmd->cmd_struct.insert_struct.i_value_count = 0;
	p_cmd->cmd_struct.insert_struct.pp_column_name = NULL;
	p_cmd->cmd_struct.insert_struct.pp_value = NULL;


	ret = get_a_word(p_cmd_str,&i_index, i_length, p_temp, &i_temp_len, MAX_NAME_LENGTH);
	// to judge that if the parse has reached the end
	if(ret == GRAMMAR_NAME_TOO_LONG)
	{
		return ret;
	}
	if(i_index == i_length || ret == GRAMMAR_REACH_END)
	{
		return GRAMMAR_EARLY_END;
	}

	if(strcmp(p_temp, p_into) != 0)
	{
		return GRAMMAR_NO_INTO;
	}

	/* ===============get the table name===============*/
	ret = get_a_word(p_cmd_str,&i_index, i_length, p_temp, &i_temp_len, MAX_NAME_LENGTH);
	// to judge that if the parse has reached the end
	if(ret == GRAMMAR_NAME_TOO_LONG)
	{
		return ret;
	}
	if(i_index == i_length || ret == GRAMMAR_REACH_END)
	{
		return GRAMMAR_EARLY_END;
	}
	strcpy(p_cmd->cmd_struct.insert_struct.p_table_name, p_temp);
	/* ===============end===============*/

	if(skip_ws(p_cmd_str, &i_index, i_length) == FALSE)
	{
		return GRAMMAR_REACH_END;
	}
	// if it is like
	/*INSERT INTO table_name (column1, column2, column3,...)
	VALUES (value1, value2, value3,...)*/
	-- i_index;
	if(p_cmd_str[i_index] == c_lbracket)
	{
		ret = get_bracket_values(
			p_cmd_str, 
			&i_index, 
			i_length, 
			&(p_cmd->cmd_struct.insert_struct.pp_column_name),
			&(p_cmd->cmd_struct.insert_struct.i_column_count),
			FALSE
			);
		if(ret == GRAMMAR_NAME_TOO_LONG)
		{
			return ret;
		}
		if(ret == GRAMMAR_REACH_END)
		{
			return GRAMMAR_EARLY_END;
		}
		if(skip_ws(p_cmd_str, &i_index, i_length) == FALSE)
		{
			return GRAMMAR_REACH_END;
		}
	}

	/* ===============Check The 'values'===============*/
	ret = get_a_word(p_cmd_str,&i_index, i_length, p_temp, &i_temp_len, MAX_NAME_LENGTH);
	// to judge that if the parse has reached the end
	if(ret == GRAMMAR_NAME_TOO_LONG)
	{
		return ret;
	}
	if(i_index == i_length || ret == GRAMMAR_REACH_END)
	{
		return GRAMMAR_EARLY_END;
	}
	if(strcmp(p_temp, p_values) != 0)
	{
		return GRAMMAR_NO_VALUES;
	}
	/* ===============end===============*/

	/* ===============get the new values===============*/
	ret = get_bracket_values(
		p_cmd_str, 
		&i_index, 
		i_length, 
		&(p_cmd->cmd_struct.insert_struct.pp_value),
		&(p_cmd->cmd_struct.insert_struct.i_value_count),
		TRUE
		);
	return ret;
	/* ===============end===============*/
}



grammar_chck_value parse_command(char* p_cmd_str, cmd_t* p_cmd)
{
	// The current size of the words array
	int i_size = 10;
	// A constant number of the amount of space allocated to words array
	int i_power = 10;
	// The length of the command
	int i_cmd_len;
	// The current index of the command
	int i_index;
	// A separate word
	char p_word[MAX_NAME_LENGTH_P1];
	// A word's length
	int i_word_len = 0;
	// 
	grammar_chck_value ret;


	i_index = 0;
	i_cmd_len = strlen(p_cmd_str);
	trim_ex(p_cmd_str, i_cmd_len);
	lower_ex(p_cmd_str, i_cmd_len);
	i_cmd_len = strlen(p_cmd_str);
	// To get the first word to specify the command
	ret = get_a_word(p_cmd_str, &i_index, i_cmd_len, p_word, &i_word_len, MAX_NAME_LENGTH);
	// terminate the loop
	if(ret == GRAMMAR_NAME_TOO_LONG)
	{
		return ret;
	}
	if(ret == GRAMMAR_REACH_END)
	{
		return GRAMMAR_EARLY_END;
	}
	// select 
	if(! strcmp(p_word, p_select))
	{
		return parse_select_command(p_cmd_str, i_index, i_cmd_len, p_cmd);
	}
	else if(! strcmp(p_word, p_update))
	{
		return parse_update_command(p_cmd_str, i_index, i_cmd_len,p_cmd);
	}
	else if(! strcmp(p_word, p_delete))
	{
		return parse_delete_command(p_cmd_str, i_index, i_cmd_len, p_cmd);
	}
	else if(! strcmp(p_word, p_insert))
	{
		return parse_insert_command(p_cmd_str, i_index, i_cmd_len, p_cmd);
	}
	else if(! strcmp(p_word, p_connect))
	{
		return parse_connect_command(p_cmd_str, i_index, i_cmd_len, p_cmd);
	}
	else if (! strcmp(p_word, p_create))
	{	
		return parse_create_command(p_cmd_str, i_index, i_cmd_len, p_cmd);
	}
	else if(! strcmp(p_word, p_run))
	{
		return parse_run_script_command(p_cmd_str, i_index, i_cmd_len, p_cmd);
	}
	else 
	{
		return GRAMMAR_UNKNOWN_CMD;
	}


	return GRAMMAR_SUCCESS;
}

grammar_chck_value split_expression(char* p_cmd_str, int *p_index, int i_length, cmd_t* p_cmd, int i_power)
{
	grammar_chck_value ret;
	expr_t temp_expr;
	expr_t **pp_expr;
	int *p_expr_count;
	int i_cur_size = 0;
	char p_temp[MAX_NAME_LENGTH_P1];
	compare_type cmp_type = AND;
	int i = 0;
	int i_word_len = 0;
	compare_type *p_cmp_type;

	switch(p_cmd->type)
	{
	case SELECT:
		pp_expr = &p_cmd->cmd_struct.select_struct.p_expr;
		p_expr_count = &p_cmd->cmd_struct.select_struct.i_condition_count;
		p_cmp_type = &p_cmd->cmd_struct.select_struct.cmp_type;
		break;
	case UPDATE:
		pp_expr = &p_cmd->cmd_struct.update_struct.p_expr;
		p_expr_count = &p_cmd->cmd_struct.update_struct.i_condition_count;
		p_cmp_type = &p_cmd->cmd_struct.update_struct.cmp_type;
		break;
	case DELETE:
		pp_expr = &p_cmd->cmd_struct.delete_struct.p_expr;
		p_expr_count = &p_cmd->cmd_struct.delete_struct.i_condition_count;
		p_cmp_type = &p_cmd->cmd_struct.delete_struct.cmp_type;
		break;
	default:
		return GRAMMAR_INVALID_CMD_TYPE;
	}
	i = 0;
	while(TRUE)
	{
		if((ret = get_expression(p_cmd_str, p_index, i_length, &temp_expr)) == GRAMMAR_SUCCESS)
		{
			append_expr(pp_expr, p_expr_count, temp_expr, i_power, &i_cur_size);
		}
		else
		{
			return ret;
		}
		if((ret = get_a_word(p_cmd_str, p_index, i_length, p_temp, &i_word_len, MAX_NAME_LENGTH)) == GRAMMAR_SUCCESS)
		{
			if (strlen(p_temp) > 0)
			{
				if(i == 0)
				{
					if(strcmp(p_temp, p_and) == 0)
					{
						cmp_type = AND;
					}
					else if(strcmp(p_temp, p_or) == 0)
					{
						cmp_type = OR;
					}
					else
					{
						return GRAMMAR_INVALID_LOGIC_OP;
					}
					(*p_cmp_type) = cmp_type;
				}
				else
				{
					if((cmp_type == AND && strcmp(p_temp, p_and) != 0) || (cmp_type == OR && strcmp(p_temp, p_or) != 0))
					{
						return GRAMMAR_UNMATCHED_LOGIC_OP;
					}
				}
			}
			else
			{
				return GRAMMAR_SUCCESS;
			}
		}
		else
		{
			return ret;
		}	
		++ i;
	}
	return GRAMMAR_SUCCESS;
}

grammar_chck_value split_equation(char* p_cmd_str, int *p_index, int i_length, cmd_t* p_cmd,  int *p_size, int i_power)
{
	grammar_chck_value ret;
	pair_t pair;
	int i = 0;
	while(TRUE)
	{
		ret = get_equation(p_cmd_str, p_index, i_length, &pair);
		if(ret == GRAMMAR_SUCCESS)
		{
			append_pair(
				&p_cmd->cmd_struct.update_struct.p_pair,
				&p_cmd->cmd_struct.update_struct.i_new_value_count,
				pair, 
				i_power,
				p_size);
		}
		else if(ret == GRAMMAR_EQUATION_END)
		{
			/*append_pair(
			&p_cmd->cmd_struct.update_struct.p_pair,
			&p_cmd->cmd_struct.update_struct.i_new_value_count,
			pair, 
			i_power,
			p_size);*/
			if( i > 0)
			{
				return GRAMMAR_SUCCESS;
			}
			else
			{
				return GRAMMAR_NO_UPDATE_VALUE;
			}
		}
		else
		{
			return ret;
		}
		++ i;
	}
}

grammar_chck_value split_ip_port(char* p_ip_port, char* p_ip, char* p_port)
{
	int i_index = 0;
	int i_ip_index = 0;
	int i_port_index = 0;

	char p_temp[4];
	int i_temp_index = 0;

	int i = 0;
	int i_count = 0;

	int i_length = strlen(p_ip_port);
	trim_ex(p_ip_port, i_length);
	// to get the ip
	while (i_index < i_length)
	{
		i_temp_index = 0;
		while (i_index < i_length  && p_ip_port[i_index] != c_dot && p_ip_port[i_index] != c_colon)
		{
			if(is_number(p_ip_port[i_index]) == TRUE)
			{
				p_temp[i_temp_index ++] = p_ip_port[i_index ];		
				++ i_index;
				if(i_temp_index == 3)
				{
					if(p_ip_port[i_index] != c_dot && p_ip_port[i_index] != c_colon)
					{
						return GRAMMAR_INVALID_CONNECT_IP;
					}
				}
			}
			else
			{
				return GRAMMAR_IP_MUST_BE_NUMBER;
			}
		}
		if(i_index == i_length)
		{
			return GRAMMAR_PORT_MUST_BE_SPECIFIED;
		}
		for(i = 0; i < i_temp_index; ++ i)
		{
			p_ip[i_ip_index ++] = p_temp[i];
		}

		if(i_count < 3)
		{
			p_ip[i_ip_index ++] = '.';
		}
		else
		{
			p_ip[i_ip_index] = 0;
		}
		++ i_count;
		if(i_count == 4 && p_ip_port[i_index] != c_colon)
		{
			return GRAMMAR_INVALID_CONNECT_IP;
		}
		else if(i_count != 4 && p_ip_port[i_index] == c_colon)
		{
			return GRAMMAR_INVALID_CONNECT_IP;
		}
		else if(i_count == 4 && p_ip_port[i_index] == c_colon)
		{
			break;
		}
		++ i_index;
	}
	if(i_index == i_length)
	{
		return GRAMMAR_PORT_MUST_BE_SPECIFIED;
	}
	//to get the port
	++ i_index;
	i_temp_index = 0;
	while (i_index < i_length)
	{
		if(is_number(p_ip_port[i_index]) == TRUE)
		{
			p_port[i_port_index ++] = p_ip_port[i_index];
			++ i_index;
			if(i_port_index == PORT_MAX_LENGTH)
			{
				if(i_index != i_length)
				{
					return GRAMMAR_PORT_IS_TOO_HUGE;
				}

			}
		}
		else
		{
			return GRAMMAR_PORT_MUST_BE_NUMBER;
		}
	}
	p_port[i_port_index] = 0;
	return GRAMMAR_SUCCESS;
}


grammar_chck_value get_connect_value(char* p_cmd_str, int *p_index, int i_length, cmd_t* p_cmd)
{
	grammar_chck_value ret;
	grammar_chck_value ret2;
	pair_t pair;
	int i = 0;
	char p_ip[IP_MAX_lENGTH_P1];
	char p_port[PORT_MAX_LENGTH_P1];

	// to get the server ip and port
	ret = get_equation(p_cmd_str, p_index, i_length, &pair);
	if(ret == GRAMMAR_SUCCESS)
	{
		if(strcmp(pair.key, p_server) == 0)
		{
			ret2 = split_ip_port(pair.value, p_ip, p_port);
			if(ret2 == GRAMMAR_SUCCESS)
			{
				strcpy(p_cmd->cmd_struct.connect_struct.server_name, p_ip);
				p_cmd->cmd_struct.connect_struct.i_server_port = atoi(p_port);
			}	
		}
		else 
		{
			return GRAMMAR_INVALID_CONNECT_STRING;
		}
	}
	else
	{
		return ret;
	}

	// to get the  user name
	free(pair.key);
	free(pair.value);
	pair.key = NULL;
	pair.value = NULL;
	ret = get_equation(p_cmd_str, p_index, i_length, &pair);
	if(ret == GRAMMAR_SUCCESS)
	{
		if(strcmp(pair.key, p_user) == 0)
		{
			if(strlen(pair.value) > MAX_USER_PWD_LENGTH)
			{
				return GRAMMAR_USER_NAME_TOO_LONG;
			}
			strcpy(p_cmd->cmd_struct.connect_struct.p_user_name, pair.value);
		}
		else 
		{
			return GRAMMAR_INVALID_CONNECT_STRING;
		}
	}
	else
	{
		return ret;
	}

	// to get the  pwd
	free(pair.key);
	free(pair.value);
	pair.key = NULL;
	pair.value = NULL;
	ret = get_equation(p_cmd_str, p_index, i_length, &pair);
	if(ret == GRAMMAR_SUCCESS)
	{
		if(strcmp(pair.key, p_password) == 0)
		{
			if(strlen(pair.value) > MAX_USER_PWD_LENGTH)
			{
				return GRAMMAR_USER_PWD_TOO_LONG;
			}
			strcpy(p_cmd->cmd_struct.connect_struct.p_user_pwd, pair.value);
		}
		else 
		{
			return GRAMMAR_INVALID_CONNECT_STRING;
		}
	}
	else
	{
		return ret;
	}

	// to get the  database name
	free(pair.key);
	free(pair.value);
	pair.key = NULL;
	pair.value = NULL;
	ret = get_equation(p_cmd_str, p_index, i_length, &pair);
	if(ret == GRAMMAR_SUCCESS)
	{
		if(strcmp(pair.key, p_database) == 0)
		{
			if(strlen(pair.value) > MAX_NAME_LENGTH)
			{
				return GRAMMAR_NAME_TOO_LONG;
			}
			strcpy(p_cmd->cmd_struct.connect_struct.p_db_name, pair.value);
		}
		else 
		{
			return GRAMMAR_INVALID_CONNECT_STRING;
		}
	}
	else
	{
		return ret;
	}
	free(pair.key);
	free(pair.value);
	return GRAMMAR_SUCCESS;
}


grammar_chck_value get_expression(char* p_cmd, int* p_index, int i_length, expr_t *p_expr)
{
	// A temporary space to store a word
	// Must be put in the upper of the pointers
	char p_temp[INFINITY_P1];
	// value's size increased by 20
	int i_value_power = 20;
	// the current value size
	int i_value_space = 0;
	// to record the dot count, can't be larger than 1
	short i_dot_count = 0;
	int i_key_len;
	int i_value_len;

	// begin getting the operator
	// skip all the whitespace 
	if(skip_ws(p_cmd, p_index, i_length) == FALSE)
	{
		return GRAMMAR_INVALID_ENDING;
	}
	// The access of pointers are statements
	i_key_len = 0;
	i_value_len = 0;
	//begin getting the key
	while((*p_index) < i_length && is_end_char(p_cmd, *p_index)  == FALSE && is_operator(p_cmd[(*p_index)]) == FALSE)
	{
		// Put the char into the word
		p_temp[i_key_len ++] = p_cmd[(*p_index)];
		if(i_key_len== MAX_NAME_LENGTH)
		{
			if(is_end_char(p_cmd, (*p_index) + 1) == FALSE)
			{
				return GRAMMAR_NAME_TOO_LONG;
			}
		}
		// Increase the index of the command
		++ (*p_index);
	}
	if((*p_index) == i_length)
	{
		return GRAMMAR_INVALID_ENDING;
	}
	p_temp[i_key_len ++] = '\0';
	p_expr->key = (char*)malloc(i_key_len * sizeof(char));
	strcpy(p_expr->key, p_temp);
	// end getting the key

	// skip all the whitespace 
	if(skip_ws(p_cmd, p_index, i_length) == FALSE)
	{
		return GRAMMAR_INVALID_ENDING;
	}

	// get the operator
	if(is_operator(p_cmd[(*p_index)]) == FALSE)
	{
		return GRAMMAR_NO_OPERATOR;
	}
	if(p_cmd[(*p_index)] == c_equal)
	{
		p_expr->com_operator = EQUAL;
	}
	else if(p_cmd[(*p_index)] == c_greater)
	{
		p_expr->com_operator = GREATER;
	}
	else 
	{
		p_expr->com_operator = SMALLER;
	}
	// end getting the operator

	// begins getting the value
	++ (*p_index);
	if(skip_ws(p_cmd, p_index, i_length) == FALSE)
	{
		return GRAMMAR_INVALID_ENDING;
	}
	// Treat the number and the string separately, different on the existence of '\''
	if(p_cmd[*p_index] == c_quote)
	{
		p_expr->type = STRING;
		++ (*p_index);
		while((*p_index) < i_length && p_cmd[*p_index] != c_quote)
		{
			append_char(&(p_expr->value), &i_value_len, p_cmd[(*p_index)], i_value_power, &i_value_space);
			++ (*p_index);
		}
		if((*p_index) == i_length )
		{
			return GRAMMAR_INVALID_ENDING;
		}
		// skip the quote
		++ (*p_index);
		p_expr->value[i_value_len ++] = '\0';
	}
	else if(is_number(p_cmd[*p_index]) == TRUE)
	{
		while((*p_index) < i_length &&((p_cmd[*p_index] >= '0' && p_cmd[*p_index] <= '9')|| p_cmd[*p_index] == c_dot))
		{
			if(p_cmd[(*p_index)] == c_dot)
			{
				++ i_dot_count;
				if(i_dot_count == 2)
				{
					return GRAMMAR_INVALID_NUMBER;
				}
			}
			append_char(&(p_expr->value), &i_value_len, p_cmd[(*p_index)], i_value_power, &i_value_space);
			++ (*p_index);
		}


		if(i_dot_count == 0)
		{
			p_expr->type = INT;
		}
		else
		{
			p_expr->type = FLOAT;
		}
		p_expr->value[i_value_len ++] = '\0';
	}
	else
	{
		return GRAMMAR_INVALID_VALUE;
	}
	// end getting the value
	return GRAMMAR_SUCCESS;
}

grammar_chck_value get_equation( char* p_cmd, int * p_index, int i_length, pair_t* p_pair)
{
	// A temporary space to store a word
	// Must be put in the upper of the pointers
	char p_temp[INFINITY_P1];
	// value's size increased by 20
	int i_value_power = 20;
	// the current value size
	int i_value_space = 0;
	// to record the dot count, can't be larger than 1
	short i_dot_count = 0;
	int i_key_len = 0;
	int i_value_len = 0;
	int i_pre_word_index;
	// SKIP all the wide space or tab character
	// If has reached the end
	if(skip_ws(p_cmd, p_index, i_length) == FALSE)
	{
		return GRAMMAR_REACH_END;
	}

	i_pre_word_index = *p_index;
	//begins getting the key
	while((*p_index) < i_length && is_end_char(p_cmd, *p_index)  == FALSE && p_cmd[(*p_index)] != c_equal)
	{
		// Put the char into the word
		p_temp[i_key_len ++] = p_cmd[(*p_index)];
		if((i_key_len) == MAX_NAME_LENGTH)
		{
			if(is_end_char(p_cmd, (*p_index) + 1) == FALSE)
			{
				return GRAMMAR_NAME_TOO_LONG;
			}
		}
		// Increase the index of the command
		++ (*p_index);
	}
	p_temp[(i_key_len) ++] = '\0';
	if(strcmp(p_temp, p_where) == 0)
	{
		(*p_index) = i_pre_word_index;
		return GRAMMAR_EQUATION_END;
	}
	if((*p_index) == i_length)
	{
		return GRAMMAR_INVALID_ENDING;
	}
	p_pair->key = (char*)malloc((i_key_len) * sizeof(char));
	strcpy(p_pair->key, p_temp);
	// end getting the key

	// begin checking the operator
	// skip all the whitespace 
	if(skip_ws(p_cmd, p_index, i_length) == FALSE)
	{
		return GRAMMAR_INVALID_ENDING;
	}
	// chk the operator
	if(p_cmd[(*p_index)] != c_equal)
	{
		return GRAMMAR_INVALID_UPDATE_VALUE;
	}
	++ (*p_index);
	// end checking the operator

	// begin getting the value
	if(skip_ws(p_cmd, p_index, i_length) == FALSE)
	{
		return GRAMMAR_INVALID_ENDING;
	}
	// Treat the number and the string separately, different on the existence of '''
	if(p_cmd[*p_index] == c_quote)
	{
		p_pair->type = STRING;
		++ (*p_index);
		while((*p_index) < i_length && p_cmd[*p_index] != c_quote)
		{
			append_char(&(p_pair->value), &i_value_len, p_cmd[(*p_index)], i_value_power, &i_value_space);
			++ (*p_index);
		}
		if((*p_index) == i_length )
		{
			return GRAMMAR_INVALID_ENDING;
		}
		// skip the quote
		++ (*p_index);
		p_pair->value[i_value_len ++] = '\0';
	}
	else if(is_number(p_cmd[*p_index]) == TRUE)
	{
		while((*p_index) < i_length &&((p_cmd[*p_index] >= '0' && p_cmd[*p_index] <= '9')|| p_cmd[*p_index] == c_dot))
		{
			if(p_cmd[(*p_index)] == c_dot)
			{
				++ i_dot_count;
				if(i_dot_count == 2)
				{
					return GRAMMAR_INVALID_NUMBER;
				}
			}
			append_char(&(p_pair->value), &i_value_len, p_cmd[(*p_index)], i_value_power, &i_value_space);
			++ (*p_index);
		}

		if(i_dot_count == 0)
		{
			p_pair->type = INT;
		}
		else
		{
			p_pair->type = FLOAT;
		}
		p_pair->value[i_value_len ++] = '\0';
	}
	else
	{
		return GRAMMAR_INVALID_VALUE;
	}
	// end getting the value
	return GRAMMAR_SUCCESS;
}


void trim_ex( char* p_char, int i_len)
{
	int i;
	int i_last_end = -1;
	for(i = 0; i < i_len; ++ i)
	{
		if(p_char[i] == c_semicolon || p_char[i] == c_tab || p_char[i] == c_ws || p_char[i] == c_new_line || p_char[i] == c_line_feed)
		{
			if(i_last_end == -1)
			{
				i_last_end = i;
			}
		}
		else 
		{
			i_last_end = -1;
		}
	}
	if(i_last_end != -1)
	{
		p_char[i_last_end]  = '\0';
	}
}
// TEST CASE: connect to server='10.60.12.1:5000' user='wangjiahao' password='tongji' database ='db'
//server='192.168.1.111:6666'; user = 'shiwen'; password = 	'shiwen'; database = 'sbdb'
grammar_chck_value parse_connect_command(char* p_cmd_str, int i_index, int i_length,cmd_t *p_cmd)
{
	grammar_chck_value ret;

	// To spare bigger space
	char p_temp[MAX_PATH_LENGTH_P1];
	int i_temp_len = 0;
	int i_cur_size = 0;
	int i_power = 4;

	p_cmd->type = CONNECT;

	/* ===============to check the keyword 'to'===============*/
	ret = get_a_word(p_cmd_str,&i_index, i_length, p_temp, &i_temp_len, MAX_NAME_LENGTH);
	if(ret == GRAMMAR_NAME_TOO_LONG)
	{
		return ret;
	}
	if(i_index == i_length || ret == GRAMMAR_REACH_END )
	{
		return GRAMMAR_EARLY_END;
	}

	if(strcmp(p_temp, p_to) != 0)
	{
		return GRAMMAR_NO_TO;
	}
	return get_connect_value(p_cmd_str, &i_index, i_length, p_cmd);
}



//create table qiyun_tb (id int not null default 1 primary key, name varchar(20), salary float);
// create table tb(student_id varchar(20), student_name varchar(10), student_score float)
// create table tb(student_id varchar(20) primary key, student_name varchar(10) not null, student_score float default 5.0)
//create table mytable (id int, name varchar(40) default 'noname' primary key not
//create table mytable (id int, name varchar(40) default 'noname' primary key not null, gender int)
grammar_chck_value get_column_value(char* p_cmd_str, int *p_index, int i_length, column* p_col)
{
	int i_count = 0;
	int i;
	int i_size = -1;
	float f_value = -1.0;
	int j = 0;
	grammar_chck_value ret;
	int i_value = -1;
	BOOL_EX b_has_dot = FALSE;
	BOOL_EX bRet;
	char p_temp[MAX_NAME_LENGTH_P1];
	// to store the 6 property words, maximum is 6
	char pp_property[6][MAX_NAME_LENGTH_P1];

	int i_temp_len = 0;

	/* ===============to check the column name===============*/
	ret = get_a_word(p_cmd_str,p_index, i_length, p_temp, &i_temp_len, MAX_NAME_LENGTH);
	if(ret == GRAMMAR_NAME_TOO_LONG)
	{
		return ret;
	}
	if((*p_index) == i_length || ret == GRAMMAR_REACH_END )
	{
		return GRAMMAR_REACH_END;
	}
	strcpy(p_col->column_name, p_temp);

	/* ===============to check the column type===============*/
	ret = get_a_word(p_cmd_str,p_index, i_length, p_temp, &i_temp_len, MAX_NAME_LENGTH);
	if(ret == GRAMMAR_NAME_TOO_LONG)
	{
		return GRAMMAR_INVALID_TYPE;
	}
	if((*p_index) == i_length || ret == GRAMMAR_REACH_END )
	{
		return GRAMMAR_EARLY_END;
	}
	if(!strcmp(p_temp, p_int))
	{
		p_col->type = INT;
	}
	else if(!strcmp(p_temp, p_float))
	{
		p_col->type = FLOAT;
	}
	else if(!strcmp(p_temp, p_varchar))
	{
		p_col->type = STRING;
		ret = get_a_word(p_cmd_str,p_index, i_length, p_temp, &i_temp_len, MAX_NAME_LENGTH);
		if(ret == GRAMMAR_NAME_TOO_LONG)
		{
			return GRAMMAR_INVALID_VARCAHR_SIZE;
		}
		if((*p_index) == i_length || ret == GRAMMAR_REACH_END )
		{
			return GRAMMAR_EARLY_END;
		}
		bRet = my_atoi(p_temp, &i_size);
		if(bRet == FALSE)
		{
			return GRAMMAR_INVALID_VARCAHR_SIZE;
		}
		else
		{
			p_col->i_column_size = i_size;
		}
	}
	else
	{
		return GRAMMAR_INVALID_TYPE;
	}
	/* ===============to get all those words in the column properties===============*/
	while((ret = get_a_word_until_comma(p_cmd_str,p_index, i_length, p_temp, &i_temp_len, MAX_NAME_LENGTH)) == GRAMMAR_SUCCESS)
	{
		if(i_count == 6)
		{
			return GRAMMAR_TOO_MANY_WORDS;
		}
		strcpy(pp_property[i_count], p_temp);
		++ i_count;
		while(p_cmd_str[(*p_index)] == c_ws)
		{
			++ (*p_index);
		}
		if(p_cmd_str[(*p_index)] == c_comma)
		{
			break;
		}
	}
	if(ret == GRAMMAR_NAME_TOO_LONG)
	{
		return GRAMMAR_INVALID_COLUMN_PROPERTY;
	}
	if((*p_index) == (i_length - 1))
	{
		ret = GRAMMAR_REACH_END;
	}
	if(i_count > 0)
	{
		// to parse the words' meaning
		if(i_count % 2 != 0)
		{
			return GRAMMAR_INVALID_COLUMN_PROPERTY;
		}
		for(i = 0; i < i_count; i += 2)
		{
			if(! strcmp(p_not, pp_property[i]))
			{
				if(! strcmp(p_null, pp_property[i + 1]))
				{
					p_col->allow_null = FALSE;
				}
				else
				{
					return GRAMMAR_INVALID_COLUMN_PROPERTY;
				}
			}
			else 	if(! strcmp(p_default, pp_property[i]))
			{
				switch (p_col->type)
				{
				case STRING:
					p_col->d_defualt_value.type = STRING;
					p_col->d_defualt_value.data.p_char_data = (char*)malloc(strlen(pp_property[i + 1]) + 1);
					strcpy(p_col->d_defualt_value.data.p_char_data, pp_property[i + 1]);
					break;
				case FLOAT:
					p_col->d_defualt_value.type = FLOAT;
					b_has_dot = FALSE;
					// CHECK THE FORMAT OF FLOAT
					j = 0;
					while (pp_property[i + 1][j])
					{
						if(pp_property[i + 1][j] != c_dot && is_number(pp_property[i + 1][j]) == FALSE)
						{
							return GRAMMAR_INVALID_FLOAT_VALUE;
						}
						if(pp_property[i + 1][j] == c_dot)
						{
							if(b_has_dot == TRUE)
							{
								return GRAMMAR_INVALID_FLOAT_VALUE;
							}
							b_has_dot = TRUE;
						}
						++ j;
					}
					f_value = (float)atof(pp_property[i + 1]);
					if(f_value == 0.0)
					{
						return GRAMMAR_INVALID_FLOAT_VALUE;
					}
					p_col->d_defualt_value.data.float_data = f_value;
					break;
				case INT:
					p_col->d_defualt_value.type = INT;
					j = 0;
					// CHECK THE FORMAT OF INT
					while (pp_property[i + 1][j])
					{
						if(is_number(pp_property[i + 1][j]) == FALSE)
						{
							return GRAMMAR_INVALID_INT_VALUE;
						}
						++ j;
					}
					bRet = my_atoi(pp_property[i + 1], &i_value);
					if(bRet == FALSE)
					{
						return GRAMMAR_INVALID_INT_VALUE;
					}
					p_col->d_defualt_value.data.int_data = i_value;
					break;
				default:
					return GRAMMAR_INVALID_TYPE;
				}		
			}
			else if(!strcmp(p_primary, pp_property[i]))
			{
				if(!strcmp(p_key, pp_property[i + 1]))
				{	
					p_col->is_one_of_key = TRUE;
				}
				else
				{
					return GRAMMAR_INVALID_COLUMN_PROPERTY;
				}
			}
		}
	}
	return GRAMMAR_SUCCESS;
}
grammar_chck_value get_create_table_value(char* p_cmd_str, int i_index, int i_length, cmd_t *p_cmd)
{
	int i_temp_len = 0;
	grammar_chck_value ret;
	column* pcolumn;
	Error_code error_code;
	char p_temp[MAX_NAME_LENGTH_P1];


	/* ===============to get the tb name===============*/
	ret = get_a_word(p_cmd_str,&i_index, i_length, p_temp, &i_temp_len, MAX_NAME_LENGTH);
	if(ret == GRAMMAR_NAME_TOO_LONG)
	{
		return ret;
	}
	if(i_index == i_length || ret == GRAMMAR_REACH_END )
	{
		return GRAMMAR_EARLY_END;
	}
	strcpy(p_cmd->cmd_struct.create_table_struct.p_table_name, p_temp);

	INIT_LIST(p_cmd->cmd_struct.create_table_struct.pcolumn_property_list);

	pcolumn = (column*)malloc(sizeof(column));	
	if(pcolumn == NULL)
		return GRAMMAR_ERROR;
	pcolumn->allow_null = -1;
	pcolumn->is_one_of_key = -1;
	pcolumn->d_defualt_value.type = -1;
	pcolumn->i_column_size = 0;

	while ((ret = get_column_value(p_cmd_str, &i_index, i_length, pcolumn)) == GRAMMAR_SUCCESS)
	{

		INSERT_POINTER(p_cmd->cmd_struct.create_table_struct.pcolumn_property_list, 
			column, 
			SIZE(p_cmd->cmd_struct.create_table_struct.pcolumn_property_list),
			pcolumn,
			error_code);
		if(error_code != ERROR_CODE_SUCCESS) 
		{
			printf("insert error in parse.c at line %d. \n", __LINE__);
			return GRAMMAR_ERROR;
		}
		pcolumn = (column*)malloc(sizeof(column));	
		if(pcolumn == NULL)
			return GRAMMAR_ERROR;
		pcolumn->allow_null = -1;
		pcolumn->is_one_of_key = -1;
		pcolumn->d_defualt_value.type = -1;
		pcolumn->i_column_size = 0;
	}
	if(SIZE(p_cmd->cmd_struct.create_table_struct.pcolumn_property_list) > 0 && ret == GRAMMAR_REACH_END) 
	{
		return GRAMMAR_SUCCESS;
	}
	return ret;
}
// create database qiyun_db max_size 20 on 'C:/db.mdf' log on 'C:/db.log' user='qiyun' password='qiyun7'
grammar_chck_value	get_create_database_value(char* p_cmd_str, int i_index, int i_length, cmd_t *p_cmd)
{
	char p_temp[MAX_PATH_LENGTH_P1];
	int i_temp_len = 0;
	grammar_chck_value ret;
	int i_max_size = -1;
	pair_t pair;


	/* ===============to get the database name===============*/
	ret = get_a_word(p_cmd_str,&i_index, i_length, p_temp, &i_temp_len, MAX_NAME_LENGTH);
	if(ret == GRAMMAR_NAME_TOO_LONG)
	{
		return ret;
	}
	if(i_index == i_length || ret == GRAMMAR_REACH_END )
	{
		return GRAMMAR_EARLY_END;
	}
	strcpy(p_cmd->cmd_struct.create_db_struct.p_db_name, p_temp);

	/* ===============to get the maxsize===============*/
	ret = get_a_word(p_cmd_str,&i_index, i_length, p_temp, &i_temp_len, MAX_NAME_LENGTH);
	if(ret == GRAMMAR_NAME_TOO_LONG)
	{
		return ret;
	}
	if(i_index == i_length || ret == GRAMMAR_REACH_END )
	{
		return GRAMMAR_EARLY_END;
	}
	if(strcmp(p_max_size, p_temp))
	{
		return GRAMMAR_NO_MAX_SIZE_SPECIFIED;
	}
	/* ===============to get the maxsize value===============*/
	ret = get_a_word(p_cmd_str,&i_index, i_length, p_temp, &i_temp_len, MAX_NAME_LENGTH);
	if(ret == GRAMMAR_NAME_TOO_LONG)
	{
		return ret;
	}
	if(i_index == i_length || ret == GRAMMAR_REACH_END )
	{
		return GRAMMAR_EARLY_END;
	}
	i_max_size = atoi(p_temp);
	// @Special The database is between 0 to 200
	if(i_max_size <= 0 || i_max_size > 200)
	{
		return GRAMMAR_ILLEGAL_DB_SIZE;
	}
	p_cmd->cmd_struct.create_db_struct.i_max_size = i_max_size;


	// on 'C:/db.mdf' log on
	/* ===============to get the 'on' keyword ===============*/
	ret = get_a_word(p_cmd_str,&i_index, i_length, p_temp, &i_temp_len, MAX_NAME_LENGTH);
	if(ret == GRAMMAR_NAME_TOO_LONG)
	{
		return ret;
	}
	if(i_index == i_length || ret == GRAMMAR_REACH_END )
	{
		return GRAMMAR_EARLY_END;
	}
	if(strcmp(p_temp, p_on))
	{
		return GRAMMAR_NO_ON;
	}

	/* ===============to get the DB file location===============*/
	ret = get_inner_quote_info(p_cmd_str,&i_index, i_length, p_temp, &i_temp_len, MAX_PATH_LENGTH);
	if(ret == GRAMMAR_NAME_TOO_LONG)
	{
		return GRAMMAR_PATH_TOO_LONG;
	}
	if(i_index == i_length || ret == GRAMMAR_REACH_END )
	{
		return GRAMMAR_EARLY_END;
	}
	strcpy(p_cmd->cmd_struct.create_db_struct.db_file, p_temp);

	/* ===============to get the 'log' keyword ===============*/
	ret = get_a_word(p_cmd_str,&i_index, i_length, p_temp, &i_temp_len, MAX_NAME_LENGTH);
	if(ret == GRAMMAR_NAME_TOO_LONG)
	{
		return ret;
	}
	if(i_index == i_length || ret == GRAMMAR_REACH_END )
	{
		return GRAMMAR_EARLY_END;
	}
	if(strcmp(p_temp, p_log))
	{
		return GRAMMAR_NO_LOG;
	}
	/* ===============to get the 'on' keyword ===============*/
	ret = get_a_word(p_cmd_str,&i_index, i_length, p_temp, &i_temp_len, MAX_NAME_LENGTH);
	if(ret == GRAMMAR_NAME_TOO_LONG)
	{
		return ret;
	}
	if(i_index == i_length || ret == GRAMMAR_REACH_END )
	{
		return GRAMMAR_EARLY_END;
	}
	if(strcmp(p_temp, p_on))
	{
		return GRAMMAR_NO_ON;
	}

	// 'C:/db.log' user='qiyun' password='qiyun7'

	/* ===============to get the log file location===============*/
	ret = get_inner_quote_info(p_cmd_str,&i_index, i_length, p_temp, &i_temp_len, MAX_PATH_LENGTH);
	if(ret == GRAMMAR_NAME_TOO_LONG)
	{
		return GRAMMAR_PATH_TOO_LONG;
	}
	if(i_index == i_length || ret == GRAMMAR_REACH_END )
	{
		return GRAMMAR_EARLY_END;
	}
	strcpy(p_cmd->cmd_struct.create_db_struct.log_file, p_temp);

	/* ===============to get the user pair===============*/
	ret  = get_equation(p_cmd_str, &i_index, i_length, &pair);
	if(ret == GRAMMAR_SUCCESS)
	{
		if(strcmp(pair.key, p_user))
		{
			return GRAMMAR_NO_USER;
		}
		if(strlen(pair.value) < MAX_USER_PWD_LENGTH_P1)
		{
			strcpy(p_cmd->cmd_struct.create_db_struct.p_user_name, pair.value);
		}
		else
		{
			return GRAMMAR_USER_NAME_TOO_LONG;
		}
	}
	else 
	{
		return ret;
	}

	free(pair.key);
	free(pair.value);

	/* ===============to get the password pair ===============*/
	ret  = get_equation(p_cmd_str, &i_index, i_length, &pair);
	if(ret == GRAMMAR_SUCCESS)
	{
		if(strcmp(pair.key, p_password))
		{
			return GRAMMAR_NO_USER;
		}
		if(strlen(pair.value) < MAX_USER_PWD_LENGTH_P1)
		{
			strcpy(p_cmd->cmd_struct.create_db_struct.p_user_pwd, pair.value);
		}
		else
		{
			return GRAMMAR_USER_NAME_TOO_LONG;
		}
	}
	else 
	{
		return GRAMMAR_INVALID_PASSWORD_PAIR;
	}
	free(pair.key);
	free(pair.value);
	return GRAMMAR_SUCCESS;
}

grammar_chck_value parse_create_command(char* p_cmd_str, int i_index, int i_length, cmd_t *p_cmd)
{
	char p_temp[MAX_NAME_LENGTH_P1];
	int i_temp_len = 0;
	grammar_chck_value ret;


	/* ===============to specify if it is going to create db or create table===============*/
	ret = get_a_word(p_cmd_str,&i_index, i_length, p_temp, &i_temp_len, MAX_NAME_LENGTH);
	if(ret == GRAMMAR_NAME_TOO_LONG)
	{
		return ret;
	}
	if(i_index == i_length || ret == GRAMMAR_REACH_END )
	{
		return GRAMMAR_EARLY_END;
	}

	// if it is create table
	if(! strcmp(p_temp, pc_table))
	{
		p_cmd->type = CREATE_TABLE;
		return get_create_table_value(p_cmd_str, i_index, i_length, p_cmd);
	}
	else if(!strcmp(p_temp, p_database))
	{
		p_cmd->type = CREATE_DB;
		return get_create_database_value(p_cmd_str, i_index, i_length, p_cmd);
	}
	else
	{
		return GRAMMAR_NO_CREATE_OBJECT;
	}
}

grammar_chck_value parse_run_script_command( char* p_cmd_str, int i_index, int i_length, cmd_t *p_cmd )
{
	grammar_chck_value ret;
	int i_temp_len;
	char p_temp[MAX_PATH_LENGTH_P1];
	p_cmd->type = RUN_SCRIPT;
	/* ===============to get the file's location===============*/
	ret = get_a_word(p_cmd_str,&i_index, i_length, p_temp, &i_temp_len, MAX_PATH_LENGTH);
	if(ret == GRAMMAR_NAME_TOO_LONG)
	{
		return GRAMMAR_FILE_NAME_TOO_LONG;
	}
	strcpy(p_cmd->cmd_struct.run_script_struct.p_file_name, p_temp);
	return GRAMMAR_SUCCESS;
}

void free_select_struct_resource( select_struct_t* select_struct )
{
	int i;

	for(i = 0; i < select_struct->i_column_name_count; i++)
	{
		free(select_struct->pp_column_name[i]);
	}

	free(select_struct->pp_column_name);

	for(i = 0; i < select_struct->i_condition_count; i++)
	{
		free(select_struct->p_expr[i].key);
		free(select_struct->p_expr[i].value);
	}

	free(select_struct->p_expr);

	for(i = 0; i < select_struct->i_table_count; i++)
	{
		free(select_struct->pp_table_name[i]);
	}

	free(select_struct->pp_table_name);
}

void free_update_struct_resource( update_struct_t* update_struct )
{
	int i;

	for(i = 0; i < update_struct->i_new_value_count; i++)
	{
		free(update_struct->p_pair[i].key);
		free(update_struct->p_pair[i].value);
	}

	free(update_struct->p_pair);

	for(i = 0; i < update_struct->i_condition_count; i++)
	{
		free(update_struct->p_expr[i].key);
		free(update_struct->p_expr[i].value);
	}
	if (update_struct->p_expr != NULL)
	{
		free(update_struct->p_expr);
	}
}

void free_delete_struct_resource( delete_struct_t* delete_struct )
{
	int i;

	for(i = 0; i < delete_struct->i_condition_count; i++)
	{
		free(delete_struct->p_expr[i].key);
		free(delete_struct->p_expr[i].value);
	}
	free(delete_struct->p_expr);
}